﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using T.FAS.Runtime.Base.Dao;
using T.FAS.Runtime.ScheduleJob.SPI;
using T.ServiceComponent.DAC.Service;
using T.ServiceComponent.DataAccessEx.Core;

namespace T.FAS.Runtime.ScheduleJob.Dao
{
    public class ScheduleJobInstanceDao : DaoService<ScheduleJobInstanceStore>
    {
        public override string TableName => "FAS_ScheduleJobInstance";
        public override string IDColumnName => "ID";

        public override List<string> ExceptColumnName
            => DaoUtil.GetExceptionColumn<ScheduleJobInstanceStore>(
                new List<string>
                {
                }
            );
        public ScheduleJobInstanceDao() : base()
        {
            DBName = "TFAS";
        }
        public override ScheduleJobInstanceStore ConvertToObject(Dictionary<string, PropertyInfo> columns, DataRow row)
        {
            if (columns.ContainsKey("ScheduleJobType"))
                columns.Remove("ScheduleJobType");
            if (columns.ContainsKey("ScheduleJobExecuteState"))
                columns.Remove("ScheduleJobExecuteState");
            if (columns.ContainsKey("ScheduleJobExecuteResult"))
                columns.Remove("ScheduleJobExecuteResult");
            if (columns.ContainsKey("TriggerType"))
                columns.Remove("TriggerType");
            var data = base.ConvertToObject(columns, row);
            data.ScheduleJobType = (Metadata.Entity.ScheduleJob.JobType)Enum.Parse(typeof(Metadata.Entity.ScheduleJob.JobType),Convert.ToString(row["ScheduleJobType"]));
            data.ScheduleJobExecuteState = (JobExecuteState)Enum.Parse(typeof(JobExecuteState),Convert.ToString(row["ScheduleJobExecuteState"]));
            data.ScheduleJobExecuteResult = (JobExecuteResult)Enum.Parse(typeof(JobExecuteResult), Convert.ToString(row["ScheduleJobExecuteResult"]));
            data.TriggerType = (Metadata.Entity.ScheduleJob.TriggerType)Enum.Parse(typeof(Metadata.Entity.ScheduleJob.TriggerType), Convert.ToString(row["TriggerType"]));
            return data;
        }
        public override Dictionary<string, object> GetDataMapping(ScheduleJobInstanceStore data)
        {
            var mapping = base.GetDataMapping(data);
            mapping.Remove("ScheduleJobType");
            mapping.Add("ScheduleJobType", (int)data.ScheduleJobType);
            mapping.Remove("ScheduleJobExecuteState");
            mapping.Add("ScheduleJobExecuteState", (int)data.ScheduleJobExecuteState);
            mapping.Remove("ScheduleJobExecuteResult");
            mapping.Add("ScheduleJobExecuteResult", (int)data.ScheduleJobExecuteResult);
            mapping.Remove("TriggerType");
            mapping.Add("TriggerType", (int)data.TriggerType);

            return mapping;
        }
        public override Dictionary<string, PropertyInfo> GetColumns()
        {
            return base.GetColumns();
        }
        public List<ScheduleJobInstanceStore> GetAllToBeExecutedScheduleJobInstances()
        {
            var queryFilter = $" ScheduleJobExecuteState <>'{(int)JobExecuteState.Deleted}'";
            var result = base.GetObjectsByFilter(queryFilter);
            var list = new List<ScheduleJobInstanceStore>();
            if (result != null && result.Count > 0)
            {
                result.ForEach(x => list.Add(x as ScheduleJobInstanceStore));
            }
            return list.OrderByDescending(x => x.LastModifyTime).ToList();
        }
        public List<ScheduleJobInstanceStore> GetAllNeedAutoStartScheduleJobInstances()
        {
            var queryFilter = $" ScheduleJobExecuteState <>'{(int)JobExecuteState.Deleted}' and ScheduleJobExecuteState<>'{(int)JobExecuteState.Pause}'";
            var result = base.GetObjectsByFilter(queryFilter);
            var list = new List<ScheduleJobInstanceStore>();
            if (result != null && result.Count > 0)
            {
                result.ForEach(x => list.Add(x as ScheduleJobInstanceStore));
            }
            return list.OrderByDescending(x => x.LastModifyTime).ToList();
        }

        public List<ScheduleJobInstanceStore> GetScheduleJobInstances(UserDefineQueryFilter filter)
        {
            var queryFilter = "1=1";
            if (filter != null && filter.Count > 0)
            {
                if (filter.ContainsKey("ScheduleJobID"))
                {
                    queryFilter += $" and ScheduleJobID ='{filter.GetStringData("ScheduleJobID")}'";
                }
                if (filter.ContainsKey("ScheduleJobState"))
                {
                    queryFilter += $" and ScheduleJobExecuteState ='{filter.GetStringData("ScheduleJobState")}'";
                }
                if (filter.ContainsKey("ScheduleJobSubscriptionID"))
                {
                    queryFilter += $" and ScheduleJobID ='{filter.GetStringData("ScheduleJobSubscriptionID")}'";
                }
            }
            var result = base.GetObjectsByFilter(queryFilter);
            var list = new List<ScheduleJobInstanceStore>();
            if (result != null && result.Count > 0)
            {
                result.ForEach(x => list.Add(x as ScheduleJobInstanceStore));
            }
            return list.OrderByDescending(x=>x.LastModifyTime).ToList();
        }
        public ScheduleJobInstanceStore GetScheduleJobInstanceByInstanceID(string instanceID)
        {
            var result = base.GetObjectsByFilter($"InstanceID='{instanceID}'");
            if (result != null && result.Count > 0)
            {
                return result[0] as ScheduleJobInstanceStore;
            }
            return null;
        }

        public void UpdateScheduleJobInstanceState(string instanceID, ScheduleJobStateNoticeData data)
        {
            if (data == null || string.IsNullOrEmpty(data.InstanceID))
                return;
            var parameterList = new List<IDbDataParameter>();
            var setStringBuilder = new StringBuilder();

            parameterList.Add(DB.MakeInParam("@InstanceID", TDbDataType.VarChar, instanceID));

            if (data.JobState != null)
            {
                parameterList.Add(DB.MakeInParam("@JobState", TDbDataType.Int, (int)data.JobState));
                setStringBuilder.Append("ScheduleJobExecuteState = @JobState");
            }
            if (data.JobResult != null)
            {
                parameterList.Add(DB.MakeInParam("@JobResult", TDbDataType.Int, (int)data.JobResult));
                setStringBuilder.Append(",ScheduleJobExecuteResult = @JobResult");
            }
            if (!string.IsNullOrEmpty(data.Message))
            {
                parameterList.Add(DB.MakeInParam("@FailReason", TDbDataType.VarChar, data.Message));
                setStringBuilder.Append(",FailReason = @FailReason");
            }
            if (data.StartTime?.Year != 1)
            {
                parameterList.Add(DB.MakeInParam("@StartTime", TDbDataType.DateTime, data.StartTime));
                setStringBuilder.Append(",StartTime = @StartTime");
            }
            if (data.EndTime?.Year != 1)
            {
                parameterList.Add(DB.MakeInParam("@EndTime", TDbDataType.DateTime, data.EndTime));
                setStringBuilder.Append(",EndTime = @EndTime");
            }
            if (setStringBuilder.Length > 0)
            {
                DB.ExecSqlStatement(string.Format("update {0} set {1} where InstanceID=@InstanceID", this.TableName,setStringBuilder.ToString()), parameterList.ToArray());
            }
        }

        public bool IsExistsInstance(string instanceID)
        {             
            var result = base.GetObjectsByFilter($"InstanceID='{instanceID}' and ScheduleJobExecuteState<>'{(int)JobExecuteState.Deleted}'");
            if (result != null && result.Count > 0)
            {
                return true;
            }
            return false;

        }
    }
}
